package main

import (
	"fmt"
	"strconv"
)

//系统启动
func welcome() {
	fmt.Println("                           welcome to my student management system")
}

//显示菜单
func showSercise() {
	fmt.Println("1. Ranking student performance")
	fmt.Println("2. Check students single score")
	fmt.Println("3. View the overall score of a subject")
	fmt.Println("4. Set the standard of a subject and classify student")
	fmt.Println("5. Check who has more than two failed subjects")
	fmt.Println("6. Delete someone data")
	fmt.Println("7. Insert someone data")
	fmt.Println("8. Revise someone data")
	fmt.Println("9. Generate student transcript")
	fmt.Println("10. Quite the software")
	fmt.Println("So If you want to use the service,please input which one do you want")
}

func servicePrint() {
	fmt.Println("Please input the next order")
	fmt.Println()
}

func rankPrint() {
	fmt.Println("Please input which subject do you want to rank")
	fmt.Println()
}

func checkPrint() {
	fmt.Println("Whose score do you want to check")
	fmt.Println()
}

func findStuPrint() {
	fmt.Println("Fail to find this student")
	fmt.Println()
}

func findSubPrint() {
	fmt.Println("Fail to find this subject")
	fmt.Println()
}

func deletePrint() {
	fmt.Println("Whose data do you want to delete")
	fmt.Println()
	fmt.Println("Please input his name")
	fmt.Println()
}

func viewPrint() {
	fmt.Println("Which subject do you want to view")
	fmt.Println()
}

func goodbye() {
	fmt.Println("                           See you again")
}

func findStudent(name string, p *Student) *Student {
	if p == nil {
		fmt.Println("error")
		return nil
	}
	var q *Student
	q = p
	for q != nil && q.studentData.studentName != name {
		q = q.next
	}
	if p == nil {
		findStuPrint()
		return nil
	}
	return q
}

func findSubject(name string, List *Node) int {
	if List.head == nil {
		fmt.Println("error")
		return 0
	}
	var p *Student
	p = List.head
	subjectNum := 1
	for subjectNum < 6 {
		if name == p.studentData.studentSubject[subjectNum].name {
			break
		}
		subjectNum++
	}
	if subjectNum > 5 {
		findSubPrint()
		return 0
	}
	return subjectNum
}

//对数据进行输入
func creatInsert(p *Student) *Student {
	p = new(Student)
	p.studentData.totalScore = 0
	p.studentData.studentSubject[1].name = "math"
	p.studentData.studentSubject[2].name = "programDesign"
	p.studentData.studentSubject[3].name = "English"
	p.studentData.studentSubject[4].name = "Chinese"
	p.studentData.studentSubject[5].name = "PE"
	fmt.Println("Please input the name of this student")
	fmt.Scan(&p.studentData.studentName)
	fmt.Println("Please input the ID of this student")
	fmt.Scan(&p.studentData.studenrID)
	fmt.Println("Please input the birth of this student")
	fmt.Scan(&p.studentData.studentBirth.year, &p.studentData.studentBirth.month, &p.studentData.studentBirth.day)
	fmt.Println("Please input the class of this student")
	fmt.Scan(&p.studentData.class)
	for i := 1; i < 6; i++ {
		fmt.Println("Please input the score of ", p.studentData.studentSubject[i].name)
		fmt.Scan(&p.studentData.studentSubject[i].score)
		p.studentData.totalScore = p.studentData.totalScore + p.studentData.studentSubject[i].score
	}
	p.studentData.failed = 0
	return p
}

//单向链表的创建和链接
func creat(List *Node) {
	fmt.Println("Please input the number of students")
	var studentNum int
	fmt.Scan(&studentNum)
	var p, tail *Student
	for i := 0; i < studentNum; i++ {
		p = creatInsert(p)
		p.next = nil
		tail = List.head
		if tail != nil {
			for tail.next != nil {
				tail = tail.next
			}
			tail.next = p
		} else {
			List.head = p
		}
	}
}

func reviseInsert(p *Student) *Student {
	if p == nil {
		fmt.Println("error")
		return nil
	}
	p.studentData.totalScore = 0
	fmt.Println("Please input the new name of this student")
	fmt.Scan(&p.studentData.studentName)
	fmt.Println("Please input the new ID of this student")
	fmt.Scan(&p.studentData.studenrID)
	fmt.Println("Please input the birth of this student")
	fmt.Scan(&p.studentData.studentBirth.year, &p.studentData.studentBirth.month, &p.studentData.studentBirth.day)
	fmt.Println("Please input his new class")
	fmt.Scan(&p.studentData.class)
	fmt.Println("Please input the number of the subject which is not passed")
	fmt.Scan(&p.studentData.failed)
	for i := 1; i < 6; i++ {
		fmt.Println("Please input the new ", p.studentData.studentSubject[i].name, " score")
		fmt.Scan(&p.studentData.studentSubject[i].score)
		p.studentData.totalScore = p.studentData.totalScore + p.studentData.studentSubject[i].score
	}
	return p
}

func setStand(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	p := List.head
	for i := 1; i < 6; i++ {
		fmt.Println("Please input the standard of ", p.studentData.studentSubject[i].name)
		var ex, ps, nps int
		fmt.Scan(&ex, &ps, &nps)
		for q := List.head; q != nil; q = q.next {
			q.studentData.studentSubject[i].stand.excellent = ex
			q.studentData.studentSubject[i].stand.passed = ps
			q.studentData.studentSubject[i].stand.noPassed = nps
			if q.studentData.studentSubject[i].score < nps {
				q.studentData.failed++
			}
		}
	}
}

func swapValue(a, b int) (c, d int) {
	return b, a
}

func swap(a, b *Student) {
	var str1, str2 string
	str1 = a.studentData.studentName
	a.studentData.studentName = b.studentData.studentName
	b.studentData.studentName = str1
	str2 = a.studentData.studenrID
	a.studentData.studenrID = b.studentData.studenrID
	b.studentData.studenrID = str2
	a.studentData.failed, b.studentData.failed = swapValue(a.studentData.failed, b.studentData.failed)
	a.studentData.class, b.studentData.class = swapValue(a.studentData.class, b.studentData.class)
	a.studentData.studentBirth.year, b.studentData.studentBirth.year = swapValue(a.studentData.studentBirth.year, b.studentData.studentBirth.year)
	a.studentData.studentBirth.month, b.studentData.studentBirth.month = swapValue(a.studentData.studentBirth.month, b.studentData.studentBirth.month)
	a.studentData.studentBirth.day, b.studentData.studentBirth.day = swapValue(a.studentData.studentBirth.day, b.studentData.studentBirth.day)
	for i := 1; i < 6; i++ {
		a.studentData.studentSubject[i].score, b.studentData.studentSubject[i].score = swapValue(a.studentData.studentSubject[i].score, b.studentData.studentSubject[i].score)
	}
	a.studentData.totalScore, b.studentData.totalScore = swapValue(a.studentData.totalScore, b.studentData.totalScore)
}

func stuInsert(p *Student) *Student {
	p = new(Student)
	if p == nil {
		fmt.Println("No enough memory")
		return nil
	}
	p.studentData.totalScore = 0
	p.studentData.failed = 0
	p.studentData.studentSubject[1].name = "math"
	p.studentData.studentSubject[2].name = "programDesign"
	p.studentData.studentSubject[3].name = "English"
	p.studentData.studentSubject[4].name = "Chinese"
	p.studentData.studentSubject[5].name = "PE"
	fmt.Println("Please input the name of this student")
	fmt.Scan(&p.studentData.studentName)
	fmt.Println("Please input the ID of this student")
	fmt.Scan(&p.studentData.studenrID)
	fmt.Println("Please input the birth of this student")
	fmt.Scan(&p.studentData.studentBirth.year, &p.studentData.studentBirth.month, &p.studentData.studentBirth.day)
	fmt.Println("Please input the class of this student")
	fmt.Scan(&p.studentData.class)
	for i := 1; i < 6; i++ {
		fmt.Println("Please input the score of ", p.studentData.studentSubject[i].name)
		fmt.Scan(&p.studentData.studentSubject[i].score)
		p.studentData.totalScore = p.studentData.totalScore + p.studentData.studentSubject[i].score
	}
	return p
}

func rankSubject(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	var str string
	rankPrint()
	fmt.Scan(&str)
	i := findSubject(str, List)
	for p := List.head; p != nil; p = p.next {
		for q := p.next; q != nil; q = q.next {
			if q.studentData.studentSubject[i].score > p.studentData.studentSubject[i].score {
				swap(p, q)
			}
		}
	}
}

func checkStudent(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	p := List.head
	checkPrint()
	var str string
	fmt.Scan(&str)
	p = findStudent(str, p)
	for i := 1; i < 6; i++ {
		fmt.Println(p.studentData.studentSubject[i].name, " ", p.studentData.studentSubject[i].score)
	}
}

func revise(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	p := List.head
	fmt.Println("Whose data do you want to revise")
	var str string
	fmt.Scan(&str)
	p = findStudent(str, p)
	p = reviseInsert(p)
}

func checkSubject(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	fmt.Println("Here are the student who failed more than two subjects")
	for p := List.head; p != nil; p = p.next {
		if p.studentData.failed > 2 {
			fmt.Println(p.studentData.studentName)
		}
	}
}

func insert(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	var p *Student
	p = stuInsert(p)
	p.next = nil
	tail := List.head
	for tail.next != nil {
		tail = tail.next
	}
	tail.next = p
}

func deleteStu(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	var str string
	deletePrint()
	fmt.Scan(&str)
	var p, q *Student
	q = nil
	for p = List.head; p != nil; p = p.next {
		if p != nil && p.studentData.studentName == str {
			if q != nil {
				q.next = p.next
			} else {
				List.head = p.next
			}
		}
		q = p
	}
}

func set(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	var p *Student
	for p = List.head; p != nil; p = p.next {
		p.studentData.failed = 0
	}
	setStand(List)
}

func view(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	var p *Student
	var str string
	viewPrint()
	fmt.Scan(&str)
	var subjectNum int
	subjectNum = findSubject(str, List)
	for p = List.head; p != nil; p = p.next {
		fmt.Println(p.studentData.studentName, " ", p.studentData.studentSubject[subjectNum].score)
	}
}

func mathScore(p *Student, i int) {
	if p == nil {
		fmt.Println("error")
		return
	}
	str := strconv.Itoa(p.studentData.studentSubject[i].score)
	fmt.Print(str)
	len1 := len(str)
	for j := 0; j < 6-len1; j++ {
		fmt.Print(" ")
	}
	fmt.Print("|")
}

func programScore(p *Student, i int) {
	if p == nil {
		fmt.Println("error")
		return
	}
	str := strconv.Itoa(p.studentData.studentSubject[i].score)
	fmt.Print(str)
	len1 := len(str)
	for j := 0; j < 16-len1; j++ {
		fmt.Print(" ")
	}
	fmt.Print("|")
}

func englishScore(p *Student, i int) {
	if p == nil {
		fmt.Println("error")
		return
	}
	str := strconv.Itoa(p.studentData.studentSubject[i].score)
	fmt.Print(str)
	len1 := len(str)
	for j := 0; j < 9-len1; j++ {
		fmt.Print(" ")
	}
	fmt.Print("|")
}

func chineseScore(p *Student, i int) {
	if p == nil {
		fmt.Println("error")
		return
	}
	str := strconv.Itoa(p.studentData.studentSubject[i].score)
	fmt.Print(str)
	len1 := len(str)
	for j := 0; j < 9-len1; j++ {
		fmt.Print(" ")
	}
	fmt.Println("|")
}

func peScore(p *Student, i int) {
	if p == nil {
		fmt.Println("error")
		return
	}
	str := strconv.Itoa(p.studentData.studentSubject[i].score)
	fmt.Print(str)
	len1 := len(str)
	for j := 0; j < 4-len1; j++ {
		fmt.Print(" ")
	}
	fmt.Print("|")
}

func generatePrint(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	fmt.Println(" ___________________________________________________________________________________________")
	fmt.Println("|Name                | class | Total score | math | English | program_design | PE | Chinese |")
	fmt.Println("|____________________|_______|_____________|______|_________|________________|____|_________|")
	for p := List.head; p != nil; p = p.next {
		fmt.Print("|")
		fmt.Print(p.studentData.studentName)
		len1 := len(p.studentData.studentName)
		for i := 0; i < 20-len1; i++ {
			fmt.Print(" ")
		}
		fmt.Print("|")
		fmt.Print(p.studentData.class)
		fmt.Print("    |")
		fmt.Print(p.studentData.totalScore)
		fmt.Print("          |")
		for i := 1; i < 6; i++ {
			switch i {
			case 1:
				mathScore(p, 1)
			case 2:
				englishScore(p, 3)
			case 3:
				programScore(p, 2)
			case 4:
				peScore(p, 5)
			case 5:
				chineseScore(p, 4)
			}
		}
		fmt.Println("|____________________|_______|_____________|______|_________|________________|____|_________|")
	}
}

func generate(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	var p, q *Student
	for p = List.head; p != nil; p = p.next {
		for q = p.next; q != nil; q = q.next {
			if q.studentData.totalScore > p.studentData.totalScore {
				swap(p, q)
			}
		}
	}
	generatePrint(List)
}

func service(List *Node) {
	if List.head == nil {
		fmt.Println("error")
		return
	}
	showSercise()
	var serviceNum int
	cnt := 0
	for {
		if cnt > 1 {
			servicePrint()
		}
		fmt.Scan(&serviceNum)
		cnt++
		switch serviceNum {
		case 1:
			rankSubject(List)
		case 2:
			checkStudent(List)
		case 3:
			view(List)
		case 4:
			set(List)
		case 5:
			checkSubject(List)
		case 6:
			deleteStu(List)
		case 7:
			insert(List)
		case 8:
			revise(List)
		case 9:
			generate(List)
		case 10:
			return
		}
	}
}
